
package ev;

import java.util.*;
import ev.*;
import ev.data.*;
import ev.operator.*;
import ev.selection.*;


public class GeneticAlgorithm implements Assignment1{
	
	
	private int limit = 20000;//terminating condition
	
	public GeneticAlgorithm() {
		
	}

	public void emulation() {
		Population initialPopulation;
		ArrayList<Individual> S;
		Individual best = null;
		ArrayList<City> cities;

		cities=MyData.getCityData();
		System.out.println("cities="+cities.size());
		initialPopulation = new Population(cities);

		int populationsize = 100;//population size set here
		
		System.out.println("generationsize="+limit);
		System.out.println("populationsize="+populationsize);
		for(int i=0; i<populationsize; i++)
		{
			initialPopulation.add(new Individual(cities.size()));
		}
		//finish retrieving, prepare to start simulation

		S = initialPopulation.getPopulation();

		int size = 25; //operate number in one generation
		best = best(S);
		System.out.println("initialBest="+best.getQuality());
		while(limit > 0)//algorithm will be terminated when limit reaches
		{
			limit--;
			//System.out.println(limit);
			Random randomGenerator = new Random();
			for(int i = 0; i < size; i++){
				int index1 = randomGenerator.nextInt(S.size());
				Individual parent1 = S.get(index1).copy();
				int index2 = randomGenerator.nextInt(S.size());
				Individual parent2 = S.get(index2).copy();
				ArrayList<Individual> children  = new cycle().cross(parent1,parent2);
				//System.out.println("i="+i);
				//System.out.println(children.size());
				for(int j = 0; j < children.size(); j++){
					Individual tmp = new Swap().mutate(children.get(j));
					if(!initialPopulation.contain(tmp)){
						initialPopulation.add(tmp);
					}
				}
				//System.out.println("PopulationSize="+initialPopulation.getPopulationSize());
				
			}
			//System.out.println(initialPopulation.getPopulationSize());
			initialPopulation = new SimpleSelection().select (initialPopulation,populationsize);
			
			S = initialPopulation.getPopulation();
			Individual tempBest = best(S);
			if(tempBest.getQuality()<best.getQuality()){
				best = tempBest;
			}
			
		}
		System.out.println("Best="+best.getQuality());
	}
	
	private Individual best(ArrayList<Individual> S){
		Individual best=null;
		Individual[] SS=new Individual[S.size()];
		for(int i=0;i<SS.length;i++){
			SS[i]=S.get(i);
		}
		Arrays.sort(SS);
//		for(int i=0;i<SS.length;i++){
//			System.out.println(SS[i].getQuality());
//		}
		best=SS[0].copy();
		return best;
	}
	
}